use std::ops::Mul;
use crate::{Vec3, Mat4};

pub struct Mat3 {
    pub m: [[f32; 3]; 3]
}

impl Mat3 {
    pub fn identity() -> Self {
        Self {
            m: [
                [1.0, 0.0, 0.0],
                [0.0, 1.0, 0.0],
                [0.0, 0.0, 1.0]
            ]
        }
    }

    pub fn as_ptr(&self) -> *const f32 {
        &self.m[0][0]
    }
}

impl Into<Mat4> for Mat3 {
    fn into(self) -> Mat4 {
        Mat4 {
            m: [
                [self.m[0][0], self.m[0][1], self.m[0][2], 0.0],
                [self.m[1][0], self.m[1][1], self.m[1][2], 0.0],
                [self.m[2][0], self.m[2][1], self.m[2][2], 0.0],
                [0.0, 0.0, 0.0, 1.0],
            ]
        }
    }
}

impl Mul<Vec3> for Mat3 {
    type Output = Vec3;

    fn mul(self, rhs: Vec3) -> Self::Output {
        Vec3(self.m[0][0] * rhs.0 + self.m[0][1] * rhs.1 + self.m[0][2] * rhs.2,
             self.m[1][0] * rhs.0 + self.m[1][1] * rhs.1 + self.m[1][2] * rhs.2,
             self.m[2][0] * rhs.0 + self.m[2][1] * rhs.1 + self.m[2][2] * rhs.2)
    }
}

impl Default for Mat3 {
    fn default() -> Self {
        Self::identity()
    }
}